/*
 * @features: 主要功能
 * @description: 内容说明
 * @Date: 2021-09-11 16:26:59
 * @Author: judu233(769471424@qq.com)
 * @LastEditTime: 2021-10-03 13:48:47
 * @LastEditors: judu233
 */
import { CCInteger } from "cc";
import { Enum, Color, SpriteFrame, Component, color, _decorator, Node, Button, __private, Sprite } from "cc";
import { EDITOR } from "cc/env";
import { ProxyOb } from "./Core/ProxyOb";
import { EventHandleCall } from "./Core/VmEvent";
import VmBase, { COMP_MAP_ARR } from "./Core/VmBase";
import c3d from "../../cc";

const { ccclass, property, menu } = _decorator;
enum PARAM_TYPE {
    index,
    name
}
/**Editor刷新页面切换时的target */
const VM_PAGE_LAYER_CHANGE = `VmPage_PageTargetLayerChange`;

/**Editor模式下设置按钮父节点触发的事件 */
const VM_PAGE_SETBTN_PARENT = `VmPage_PageSetBtnParent`;

@ccclass(`VmPagePageHandel`)
class VmPagePageHandel extends EventHandleCall { }

@ccclass(`VmPageBtnChange`)
class VmPageBtnChange {
    @property({ type: Enum(Button.Transition) })
    transition: __private.cocos_ui_button_Transition = Button.Transition.NONE;

    @property({ visible() { return this.transition === Button.Transition.COLOR } })
    hoverColor: Color = color(255, 255, 255);

    @property({ visible() { return this.transition === Button.Transition.COLOR } })
    normalColor: Color = color(214, 214, 214);

    @property({ visible() { return this.transition === Button.Transition.COLOR } })
    pressedColor: Color = color(211, 211, 211);

    @property({ visible() { return this.transition === Button.Transition.COLOR } })
    disabledColor: Color = color(124, 124, 124);

    @property({ type: SpriteFrame, visible() { return this.transition === Button.Transition.SPRITE } })
    normalSprite: SpriteFrame = null;

    @property({ type: SpriteFrame, visible() { return this.transition === Button.Transition.SPRITE } })
    pressedSprite: SpriteFrame = null;

    @property({ type: SpriteFrame, visible() { return this.transition === Button.Transition.SPRITE } })
    hoverSprite: SpriteFrame = null;

    @property({ type: SpriteFrame, visible() { return this.transition === Button.Transition.SPRITE } })
    disabledSprite: SpriteFrame = null;

    @property({ visible() { return this.transition === Button.Transition.SCALE || this.transition === Button.Transition.COLOR } })
    duration: number = 1.0;

    @property({ visible() { return this.transition === Button.Transition.SCALE } })
    zoomScale: number = 1.1;

    @property({ type: Enum(PARAM_TYPE) })
    paramType: PARAM_TYPE = PARAM_TYPE.index;
}

@ccclass(`VmPageLayer`)
class VmPageLayer {
    @property
    private _forEachChild = true;
    public get forEachChild() { return this._forEachChild; }
    @property({ displayName: `遍历子节点`, tooltip: `遍历子节点绑定切换页面` })
    public set forEachChild(value) {
        this._forEachChild = value;
        c3d.director.emit(VM_PAGE_LAYER_CHANGE);
    }

    @property({ displayName: `影响的节点`, type: [Node], visible() { return !this.forEachChild } })
    userTarget: Node[] = [];

    @property({ displayName: `是否是循环页面` })
    isLoopPage: boolean = false;

    /**上一个index */
    preIndex: number = -1;

    /**当前index */
    @property
    private _index: number = 0;
    public get index(): number { return this._index; }
    @property({ type: CCInteger })
    public set index(v: number) {
        if (this.isChanging) return;
        v = this.checkIndex(v);
        this.preIndex = this._index;//标记之前的页面
        this._index = v;
        this.updatePage(v);
    }

    //判断是否在 changing 页面状态
    private _isChanging: boolean = false;
    public get isChanging(): boolean { return this._isChanging; }

    /**检查Index是否符合 */
    checkIndex(v: number) {
        let count = this.userTarget.length - 1;
        v = Math.round(v);
        if (this.isLoopPage) {
            if (v > count) v = 0;
            if (v < 0) v = count;
        } else {
            if (v > count) v = count;
            if (v < 0) v = 0;
        }
        return v;
    }

    /**更新切换 */
    updatePage(page: number) {
        try {
            if (EDITOR) {
                for (let [i, node] of this.userTarget.entries()) {
                    node.active = (i == page);
                }
            } else {
                if (this.preIndex === this.index) return;//没有改变就不进行操作
                if (this.preIndex != -1)
                    this.userTarget[this.preIndex].active = false;
                this.userTarget[this.index].active = true;
            }
        } catch (err) {
            c3d.error(`设置按钮参数错误，index查找失败`);
        }
    }
}

@ccclass(`VmPageBtn`)
class VmPageBtn {
    @property({ displayName: `切换按钮设置`, type: VmPageBtnChange })
    btnChangeSet: VmPageBtnChange = new VmPageBtnChange();

    @property({ displayName: `切换按钮回调`, type: VmPagePageHandel })
    touchEventsHandle: VmPagePageHandel = new VmPagePageHandel();

    @property({ displayName: `按钮节点的父节点`, tooltip: `切换按钮组的父节点`, type: Node })
    btnNodeParent: c3d.Node = null;
}

@ccclass(`VmPage`)
@menu('VM/VM-Page')
export default class VmPage extends VmBase {
    /**代理的实体组件*/
    proxy: ProxyOb<VmPage>['proxy'];

    @property(VmPageLayer)
    pageLayer = new VmPageLayer();

    @property(VmPageBtn)
    pageBtn = new VmPageBtn();

    onLoad() {
        this.watch._controllerIsWatchDeep = true;
        super.onLoad();
    }

    onEditor() {
        super.onEditor();
        c3d.director.on(VM_PAGE_LAYER_CHANGE, this.updateTargetNode, this);
        //添加点击事件
        if (this.pageBtn.touchEventsHandle.compEvents.length == 0 && this.pageBtn.btnNodeParent) {
            let eventHandle = this.createEventHandle<VmPage>(this.node, 'VmPage', 'fast_setEventIndex');
            this.pageBtn.touchEventsHandle.compEvents.push(eventHandle);
        }
        this.updateTargetNode();
    }

    onDataInit() {
        this.updateTargetNode();
        this._bindToggoleNode();
        this.pageLayer.userTarget.forEach(node => node.active = false);
        this.pageLayer.updatePage(this.pageLayer.index);
        this._setIndex(ProxyOb.getValue(this.watch.path));
    }

    /**由于开启了深遍历绑定，所以必须过滤其他监听 */
    bindComPropertyChange(newValue: any, oldValue: any, key: string, receiver: any) {
        let p = this.watch.path.split('.');
        if (key == p[p.length - 1])
            super.bindComPropertyChange(newValue, oldValue, key, receiver)
    }

    /**检查观察组件 */
    _checkComponent() {
        let arr = COMP_MAP_ARR.get(this.watch.componentName);
        this.watch._watchComponent = this.getComponent(arr[0]);
        if (!this.watch._watchComponent || !this.watch.componentProperty) {
            c3d.warn(`节点${this.node.name}未设置需要监听的组件/属性`);
            return false;
        }
        if (!this.watch._watchComponent.enabled)
            return false;
        return true;
    }


    /**更新'切换页面'影响的节点 */
    private updateTargetNode() {
        this.pageLayer.userTarget = this.pageLayer.forEachChild ? this.node.children : this.pageLayer.userTarget;
    }

    /**快速切换下一页 */
    fast_next(e) {
        if (this.pageLayer.isChanging) {
            return false;
        } else {
            this._setIndex(++this.pageLayer.index);
            return true;
        }
    }
    /**快速切换上一页 */
    fast_previous(e) {
        if (this.pageLayer.isChanging) {
            return false;
        } else {
            this._setIndex(--this.pageLayer.index);
            return true;
        }
    }
    /*切换到指定的页面，按钮设置， 或事件设置 */
    fast_setEventIndex(e, index) {
        if (this.pageLayer.index >= 0 && this.pageLayer.index != null && !this.pageLayer.isChanging) {
            this._setIndex(index);
            return true;
        } else {
            return false;
        }
    }

    /**设置 */
    private _setIndex(index: number) {
        this.pageLayer.index = index;
        this.proxy.pageLayer.index = index;
    }

    /**绑定切换按钮 */
    private _bindToggoleNode() {
        this.pageBtn.btnNodeParent?.children.forEach((node, nodeIndex) => {
            let comp = node.getComponent(Button) ?? node.addComponent(Button);
            comp.transition = this.pageBtn.btnChangeSet.transition;
            //同步属性
            if (this.pageBtn.btnChangeSet.transition == Button.Transition.SCALE) {
                comp.target = node;
                comp.transition = this.pageBtn.btnChangeSet.transition;
                comp.zoomScale = this.pageBtn.btnChangeSet.zoomScale;
            } else if (this.pageBtn.btnChangeSet.transition == Button.Transition.COLOR) {
                comp.hoverColor = this.pageBtn.btnChangeSet.hoverColor;
                comp.normalColor = this.pageBtn.btnChangeSet.normalColor;
                comp.pressedColor = this.pageBtn.btnChangeSet.pressedColor;
                comp.disabledColor = this.pageBtn.btnChangeSet.disabledColor;
            } else if (this.pageBtn.btnChangeSet.transition == Button.Transition.SPRITE) {
                comp.disabledSprite = this.pageBtn.btnChangeSet.disabledSprite;
                comp.hoverSprite = this.pageBtn.btnChangeSet.hoverSprite;
                comp.normalSprite = this.pageBtn.btnChangeSet.normalSprite;
                comp.pressedSprite = this.pageBtn.btnChangeSet.pressedSprite;
            }

            //绑定回调事件
            // c3d.log(`绑定回调事件,节点名字${node.name}`);
            comp.clickEvents = [];
            this.pageBtn.touchEventsHandle.compEvents.forEach((event) => {
                //克隆数据，每个节点获取的都是不同的回调
                let hd = this.copyEventHandle(event);

                //自动设置绑定切换index
                if (this.pageBtn.btnChangeSet.paramType === PARAM_TYPE.index) {
                    hd.customEventData = nodeIndex.toString();
                } else {
                    hd.customEventData = node.name;
                }
                comp.clickEvents.push(hd);
            });
        });
    }

}
